// 除非遵守许可证，否则不得使用此文件。
// 您可以通过
// 
// www.apache.org/licenses/LICENSE-2.0 
// 
// 除非适用法律要求或书面同意，否则根据许可证分发的软件
// 按“原样”分发，
// 无任何明示或暗示的保证或条件。
// 请参阅许可证，了解管理许可的特定语言和
// 许可证下的限制。

package endpoints

import (
	"context"

	clientv3 "go.etcd.io/etcd/client/v3"
)

// 端点表示可以建立连接的单个地址。
// 
// 灵感来自：https:
// 请记录每个字段受支持的etcd版本。
type Endpoint struct {
	// Addr是将在其上建立连接的服务器地址。
	// 因为etcd 3.1 
	Addr string

	// 元数据是与Addr关联的信息，可以使用
	// 做出负载平衡决策。
	// 因为etcd 3.1 
	Metadata interface{}
}

type Operation uint8

const (
	// 添加表示添加了端点。
	Add Operation = iota
	// 删除表示删除了现有地址。
	Delete
)

// 更新描述端点的单个编辑操作。
type Update struct {
	// Op-操作添加或删除。
	Op       Operation
	Key      string
	Endpoint Endpoint
}

// WatchChannel用于发送有关端点更新的通知。
type WatchChannel <-chan []*Update

// Key2EndpointMap将etcd键映射到描述端点的结构中。
type Key2EndpointMap map[string]Endpoint

// UpdateWithOpts将端点更新（添加或删除）与etcd选项（例如，将端点附加到租约）一起描述。
type UpdateWithOpts struct {
	Update
	Opts []clientv3.OpOption
}

// NewAddUpdateOpts为端点注册构造更新路径。
func NewAddUpdateOpts(key string, endpoint Endpoint, opts ...clientv3.OpOption) *UpdateWithOpts {
	return &UpdateWithOpts{Update: Update{Op: Add, Key: key, Endpoint: endpoint}, Opts: opts}
}

// newDeleteUpdatePts为端点删除构造更新路径。
func NewDeleteUpdateOpts(key string, opts ...clientv3.OpOption) *UpdateWithOpts {
	return &UpdateWithOpts{Update: Update{Op: Delete, Key: key}, Opts: opts}
}

// 管理器可用于为特定目标添加/删除和检查存储在etcd中的端点。
type Manager interface {
	// 更新允许从etcd中自动添加/删除几个端点。
	Update(ctx context.Context, updates []*UpdateWithOpts) error

	// AddEndpoint在etcd中注册一个端点。
	// 对于更高级的用例，请使用更新方法。
	AddEndpoint(ctx context.Context, key string, endpoint Endpoint, opts ...clientv3.OpOption) error
	// DeleteEndpoint删除etcd中存储的单个端点。
	// 对于更高级的用例，请使用更新方法。
	DeleteEndpoint(ctx context.Context, key string, opts ...clientv3.OpOption) error

	// 列表以映射的形式返回当前目标的所有端点。
	List(ctx context.Context) (Key2EndpointMap, error)
	// NewWatchChannel创建一个填充或端点更新的通道。
	// 取消“ctx”以关闭观察程序。
	NewWatchChannel(ctx context.Context) (WatchChannel, error)
}
